using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.ServiceModel;
using System.Threading;
using AutoMapper;
using Core;
using IglooCoder.Commons.WcfNhibernate;
using Infrastucture;
using NHibernate;
using WcfService1.DTO;
using Omu.ValueInjecter;

namespace WcfService1
{
    // NOTE: You can use the "Rename" command on the "Refactor" BTB to change the class name "BTBServices" in code, svc and config file together.
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    [NHibernateContext]
    public class BTBServices : IBTBServices
    {
        private readonly ItemRepository ItemRepository;
        private readonly PurchaseOrderRepository PORepository;
        private readonly InventoryRepository _InventoryRepository;
        private readonly WcfSessionStorage session;
        private BTBRepository BTBRepository;
        private MutasiStokRepository _MutasiRepository;
        private InventoryWarehouseRepository _iwRepository;
        private PurchaseInvoiceRepository PIRepository;

        public BTBServices()
        {
            Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
            session = new WcfSessionStorage();
            BTBRepository = new BTBRepository(session);
            ItemRepository = new ItemRepository(session);
            _InventoryRepository = new InventoryRepository(session);
            _MutasiRepository = new MutasiStokRepository(session);
            PORepository = new PurchaseOrderRepository(session);
            _iwRepository = new InventoryWarehouseRepository(session);
            PIRepository = new PurchaseInvoiceRepository(session);
        }

        #region IBTBServices Members

        public List<BTBDTO> GetList(int page, out long recordCount, string sortProperty = null, string sortType = "ASC")
        {
            var BTBs = new List<BTB>();
            var Results = new List<BTBDTO>();

            if (string.IsNullOrEmpty(sortProperty))
            {
                BTBs = BTBRepository.GetDataPaged(page, 30, "TglBtb", "DESC").ToList();
            }
            else
            {
                BTBs = BTBRepository.GetDataPaged(page, 30, sortProperty, sortType).ToList();
            }

            recordCount = BTBRepository.RecordCount;

            foreach (var b in BTBs)
            {
                var dto = new BTBDTO();
                dto.NoBtb = b.NoBtb;
                dto.Description = b.Description;
                dto.PurchaseOrder = new PurchaseOrderDTO {PONumber = b.PurchaseOrder.PONumber};
                dto.Status = (Status) b.Status;
                dto.Supplier = new SupplierDTO {SupplierName = b.Supplier.SupplierName};
                dto.TglBtb = b.TglBtb;
                dto.NoPI = b.PINo;
                Results.Add(dto);
            }
           

            return Results;
        }

        public bool Save(BTBDTO BTBDTO)
        {
            bool res;
            bool IsNew = false;
            try
            {
                BTB BTB = BTBRepository.GetDataOne(x => x.NoBtb == BTBDTO.NoBtb);

                if (BTB == null)
                {
                    BTB = new BTB();
                    IsNew = true;
                }

                BTBRepository.ExecuteTransactionNative(() =>
                                                           {
                                                               if (!IsNew)
                                                               {
                                                                   //Jika Status Void dan Close tdk boleh Update
                                                                   if (BTB.Status == (int)Status.Void || BTB.Status == (int)Status.Close)
                                                                       throw new Exception("Tidak bisa di Update Status sudah Close atau Void!");

                                                                   _MutasiRepository.DeleteMutasiStok(BTB.NoBtb);
                                                                   BTBRepository.Delete(BTB);
                                                                   foreach (var btbDetail in BTB.BtbDetails)
                                                                   {
                                                                       Inventory inventory =
                                                                             _InventoryRepository.GetDataOne(x =>
                                                                                 x.SerialNumber == btbDetail.NoLog);
                                                                       if (inventory != null)
                                                                           _InventoryRepository.Delete(inventory);
                                                                   }

                                                                   var NewBTB = new BTB();
                                                                   NewBTB.modified_date = DateTime.Now;
                                                                   NewBTB.created_date = BTB.created_date;
                                                                   Mapper.Map(BTBDTO, NewBTB);
                                                                   foreach (var btbDetail in NewBTB.BtbDetails)
                                                                       btbDetail.Btb = NewBTB;
                                                                   BTBRepository.Session.SaveOrUpdateCopy(NewBTB);

                                                                   foreach (BTBDetail btbDetail in NewBTB.BtbDetails)
                                                                   {
                                                                       var inventory = new Inventory();
                                                                       Mapper.Map(btbDetail, inventory);
                                                                       inventory.IsStock = true;
                                                                       _InventoryRepository.SaveOrUpdate(inventory);

                                                                       //Mutasi Masuk
                                                                       var mutasiStok = new MutasiStok();
                                                                       mutasiStok.ReferenceNumber = BTB.NoBtb;
                                                                       mutasiStok.SerialNumber = inventory.SerialNumber;
                                                                       mutasiStok.TglMutasi = BTB.TglBtb.ToDateTime();
                                                                       mutasiStok.Type = BTB.GetType().Name;
                                                                       mutasiStok.QtyMasuk = btbDetail.QtyUnit;
                                                                       var mutasiLast = _MutasiRepository.FindLastMutasi(
                                                                           inventory.SerialNumber, 
                                                                           btbDetail.Warehouse.KodeWarehouse
                                                                           ,mutasiStok.TglMutasi
                                                                           );
                                                                       if (mutasiLast == null) mutasiLast = new MutasiStok();
                                                                       mutasiStok.QtySisa = mutasiLast.QtySisa +
                                                                                                mutasiStok.QtyMasuk;
                                                                       mutasiStok.SheetMasuk = btbDetail.Tinggi;
                                                                       mutasiStok.SheetSisa = mutasiLast.SheetSisa +
                                                                                              mutasiStok.SheetMasuk;
                                                                       mutasiStok.KodeWarehouse =
                                                                           btbDetail.Warehouse.KodeWarehouse;
                                                                       _MutasiRepository.SaveOrUpdate(mutasiStok,btbDetail.KodePallet);
                                                                   }
                                                               }
                                                               else
                                                               {
                                                                   Mapper.Map(BTBDTO, BTB);
                                                                   //Untuk New entry dari transaksi bukan dari email
                                                                   if (String.IsNullOrEmpty(BTB.NoBtb))
                                                                        BTB.NoBtb = GetLastBTBNo();

                                                                   foreach (BTBDetail btbDetail in BTB.BtbDetails)
                                                                   {
                                                                       //yang dari email detailID harus diset 0
                                                                       btbDetail.Btb = BTB;
                                                                       btbDetail.BtbDetailId = 0;

                                                                       Inventory inventory =
                                                                           _InventoryRepository.GetDataOne(
                                                                               x => x.SerialNumber == btbDetail.NoLog);
                                                                       if (inventory ==null )
                                                                       {
                                                                           inventory = new Inventory();
                                                                           Mapper.Map(btbDetail, inventory);
                                                                           inventory.IsStock = true;
                                                                           _InventoryRepository.SaveOrUpdate(inventory);
                                                                       }

                                                                       //Mutasi Masuk
                                                                       var mutasiStok = new MutasiStok();
                                                                       mutasiStok.ReferenceNumber = BTB.NoBtb;
                                                                       mutasiStok.SerialNumber = inventory.SerialNumber;
                                                                       mutasiStok.TglMutasi = BTB.TglBtb.ToDateTime();
                                                                       mutasiStok.Type = BTB.GetType().Name;
                                                                       mutasiStok.QtyMasuk = btbDetail.QtyUnit;
                                                                       var mutasiLast = _MutasiRepository.FindLastMutasi
                                                                           (inventory.SerialNumber, 
                                                                           btbDetail.Warehouse.KodeWarehouse
                                                                           ,mutasiStok.TglMutasi
                                                                           );
                                                                       if (mutasiLast == null) mutasiLast = new MutasiStok();
                                                                       mutasiStok.QtySisa = mutasiLast.QtySisa +
                                                                                                mutasiStok.QtyMasuk;
                                                                       mutasiStok.SheetMasuk = btbDetail.Tinggi;
                                                                       mutasiStok.SheetSisa = mutasiLast.SheetSisa +
                                                                                              mutasiStok.SheetMasuk;
                                                                       mutasiStok.KodeWarehouse =
                                                                           btbDetail.Warehouse.KodeWarehouse;
                                                                       _MutasiRepository.SaveOrUpdate(mutasiStok,btbDetail.KodePallet);
                                                                   }

                                                                   BTBRepository.SaveOrUpdate(BTB);
                                                               }
                                                            
                                                           });

                res = true;
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return res;
        }


        public bool Delete(BTBDTO BTBDto)
        {
            bool res;
            try
            {
                BTB BTB = BTBRepository.GetDataOne(x => x.NoBtb == BTBDto.NoBtb);

                BTBRepository.ExecuteTransactionNative(
                    () =>
                        {
                            foreach (BTBDetail btbDetail in BTB.BtbDetails)
                            {
                                //Inventory inventory =
                                //    _InventoryRepository.GetDataOne(x => x.SerialNumber == btbDetail.NoLog);
                                //_InventoryRepository.Delete(inventory);
                            }
                            _MutasiRepository.DeleteMutasiStok(BTB.NoBtb);
                            BTB.Status = 2;
                            BTBRepository.SaveOrUpdate(BTB);
                            //BTBRepository.Delete(BTB);
                        }
                    );


                res = true;
            }
            catch (Exception)
            {
                res = false;
            }

            return res;
        }


        public List<BTBDTO> GetListByCriteria(Dictionary<String, Object> criteria, string expression, int page,
                                              out long recordCount)
        {
            var BTBs = new List<BTB>();
            var Results = new List<BTBDTO>();
            BTBs = BTBRepository.GetDataPaged(criteria, expression, page, 30).ToList();
            recordCount = BTBRepository.RecordCount;
            foreach (var b in BTBs)
            {
                var dto = new BTBDTO();
                dto.NoBtb = b.NoBtb;
                dto.Description = b.Description;
                dto.PurchaseOrder = new PurchaseOrderDTO { PONumber = b.PurchaseOrder.PONumber };
                dto.Status = (Status)b.Status;
                dto.Supplier = new SupplierDTO { SupplierName = b.Supplier.SupplierName };
                dto.TglBtb = b.TglBtb;
                dto.NoPI = b.PINo;
                Results.Add(dto);
            }

            return Results;
        }


        public List<BTBDTO> GetAllBTB()
        {
            List<BTB> BTBs = BTBRepository.GetDataList(x=>x.Status==0).ToList();
            List<BTBDTO> Results = BTBs.Select(x => new BTBDTO {NoBtb = x.NoBtb}).ToList();
            return Results;
        }


        public BTBDTO GetBTB(String kodeBTB)
        {
            BTB BTB = BTBRepository.GetDataOne(x => x.NoBtb == kodeBTB);
            var BTBDto = new BTBDTO();
            BTBDto.InjectFrom<CloneInjection>(BTB);
            return BTBDto;
        }

        public List<BTBDTO> GetBTBList(string kodeBTB)
        {
            List<BTB> BTBs = BTBRepository.GetDataList(x => x.NoBtb.Contains(kodeBTB)).ToList();
            var Results = new List<BTBDTO>();
            BTBs.ForEach(x =>
                             {
                                 var BTBDto = new BTBDTO();
                                 Mapper.Map(x, BTBDto);
                                 Results.Add(BTBDto);
                             }
                );

            return Results;
        }

        public string GetLastBTBNo()
        {
            var appParamServices = new AppParamServices();
            AppParamDTO param = appParamServices.GetAppParamList("KodeBTB").FirstOrDefault();
            string res = BTBRepository.GetMaxNumber(param.AppParamValue);
           
            if (string.IsNullOrEmpty(res))
                res =  param.AppParamValue;

            string formatSO = "0000";
            string kodeSO;
            string lastNo = string.Empty;

            if (res.Length <= 4)
            {
                kodeSO = res;
                lastNo = formatSO;
            }
            else
            {
                lastNo = res.Split(new[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[2];
                kodeSO = res.Split(new[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[0];
            }
            string soNum = formatSO.Substring(0, formatSO.Length - (int.Parse(lastNo) + 1).ToString().Length) +
                           (int.Parse(lastNo) + 1);

            return  kodeSO + "/" + DateTime.Now.Year + "/" + soNum;
        }

        public Decimal GetSatuanPengali(ItemDTO itemDto)
        {
            Item item = ItemRepository.GetDataOne(x => x.ItemId == itemDto.ItemId);
            return item.Satuan.Pengali;
        }

        public bool DeleteDetail(BTBDetailDTO BTBDetailDto)
        {
            bool res;
            try
            {
                var PIDetail = BTBRepository.Session.Get<BTBDetail>(BTBDetailDto.BtbDetailId);
                BTBRepository.ExecuteTransactionNative(
                    () =>
                        {
                            Inventory inventory = _InventoryRepository.GetDataOne(x => x.SerialNumber == PIDetail.NoLog);
                            _MutasiRepository.DeleteMutasiStok(BTBDetailDto.NoBtb, BTBDetailDto.NoLog);
                            _InventoryRepository.Delete(inventory);    
                            BTBRepository.DeleteDetail(PIDetail, BTBDetailDto.BtbDetailId);
                        }
                    );


                res = true;
            }
            catch (Exception)
            {
                res = false;
            }

            return res;
        }


        public bool SendEmail(BTBDTO Btbdto, String DestinationFolder)
        {
            var mailServices = new MailServices();
            BTB BTB = BTBRepository.GetDataOne(x => x.NoBtb == Btbdto.NoBtb);
            Btbdto = Mapper.Map(BTB, Btbdto);
            return mailServices.SendEmail(Btbdto,DestinationFolder);
        }

        #endregion
    }
}